package tasks

/*
   Copyright 2013 Am Laher

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

import (
	htemplate "html/template"
	"os"
	"path/filepath"
	"strings"
	"text/template"
)

//runs automatically
func init() {
	Register(Task{
		TASK_DOWNLOADS_PAGE,
		"Generate a downloads page from a template. Default outputs a Markdown page.",
		runTaskDownloadsPage,
		map[string]interface{}{
			"filename":     "downloads.md",
			"outputFormat": "by-file-extension", // use by-file-extension, markdown or html
			"templateText": `---
layout: default
title: Downloads
---

{{.AppName}} downloads (version {{.Version}})

{{range $k, $v := .Categories}}### {{$k}}

{{range $v}} * [{{.Text}}]({{.RelativeLink}})
{{end}}
{{end}}

{{.ExtraVars.footer}}`,
			"templateFile":      "",
			"templateExtraVars": map[string]interface{}{"footer": "Generated by goxc"}}})

}

type Download struct {
	Text         string
	RelativeLink string
}
type Report struct {
	AppName    string
	Version    string
	Categories map[string]*[]Download
	ExtraVars  map[string]interface{}
}

func runTaskDownloadsPage(tp TaskParams) error {
	outFilename := tp.Settings.GetTaskSettingString(TASK_DOWNLOADS_PAGE, "filename")
	templateText := tp.Settings.GetTaskSettingString(TASK_DOWNLOADS_PAGE, "templateText")
	templateFile := tp.Settings.GetTaskSettingString(TASK_DOWNLOADS_PAGE, "templateFile")
	format := tp.Settings.GetTaskSettingString(TASK_DOWNLOADS_PAGE, "outputFormat")
	if format == "by-file-extension" {
		if strings.HasSuffix(outFilename, ".md") || strings.HasSuffix(outFilename, ".markdown") {
			format = "markdown"
		} else if strings.HasSuffix(outFilename, ".html") || strings.HasSuffix(outFilename, ".htm") {
			format = "html"
		} else {
			//unknown ...
			format = ""
		}
	}
	templateVars := tp.Settings.GetTaskSettingMap(TASK_DOWNLOADS_PAGE, "templateExtraVars")
	reportFilename := filepath.Join(tp.OutDestRoot, tp.Settings.GetFullVersionName(), outFilename)
	flags := os.O_WRONLY | os.O_TRUNC | os.O_CREATE
	out, err := os.OpenFile(reportFilename, flags, 0600)
	if err != nil {
		return err
	}
	defer out.Close()
	report := Report{tp.AppName, tp.Settings.GetFullVersionName(), map[string]*[]Download{}, templateVars}
	versionDir := filepath.Join(tp.OutDestRoot, tp.Settings.GetFullVersionName())
	err = filepath.Walk(versionDir, func(path string, info os.FileInfo, e error) error {
		return downloadsWalkFunc(path, info, e, tp, report, outFilename, format)
	})
	if err != nil {
		return err
	}
	err = runTemplate(reportFilename, templateFile, templateText, out, report, format)
	if err != nil {
		return err
	}
	return out.Close()
}
func runTemplate(reportFilename, templateFile, templateText string, out *os.File, data interface{}, format string) (err error) {
	var tmpl *template.Template
	var htmpl *htemplate.Template
	if templateFile != "" {
		if format == "html" {
			htmpl, err = htemplate.New(templateFile).ParseGlob(templateFile)
		} else {
			tmpl, err = template.New(templateFile).ParseGlob(templateFile)
		}
	} else {
		if format == "html" {
			htmpl, err = htemplate.New(reportFilename).Parse(templateText)
		} else {
			tmpl, err = template.New(reportFilename).Parse(templateText)
		}
	}
	if err != nil {
		return err
	}
	if format == "html" {
		err = htmpl.Execute(out, data)
	} else {
		err = tmpl.Execute(out, data)
	}
	if err != nil {
		return err
	}

	return err
}

func getCategory(relativePath string) string {
	category := "Other files"
	if strings.Contains(relativePath, "linux") || strings.HasSuffix(relativePath, ".deb") {
		category = "Linux"
	} else if strings.Contains(relativePath, "darwin") {
		category = "Darwin (Apple Mac)"
	} else if strings.Contains(relativePath, "netbsd") {
		category = "NetBSD"
	} else if strings.Contains(relativePath, "freebsd") {
		category = "FreeBSD"
	} else if strings.Contains(relativePath, "windows") {
		category = "MS Windows"
	} else if strings.Contains(relativePath, "openbsd") {
		category = "OpenBSD"
	} else if strings.Contains(relativePath, "plan9") {
		category = "Plan 9"
	}
	return category
}

func downloadsWalkFunc(fullPath string, fi2 os.FileInfo, err error, tp TaskParams, report Report, reportFilename, format string) error {
	if fi2.IsDir() || fi2.Name() == reportFilename {
		return nil
	}

	versionDir := filepath.Join(tp.OutDestRoot, tp.Settings.GetFullVersionName())
	relativePath := strings.Replace(fullPath, versionDir, "", -1)
	relativePath = strings.TrimPrefix(relativePath, "/")
	text := fi2.Name()
	if format == "markdown" {
		text = strings.Replace(text, "_", "\\_", -1)
	}
	category := getCategory(relativePath)

	//log.Printf("Adding: %s", relativePath)
	download := Download{text, relativePath}
	v, ok := report.Categories[category]
	var existing []Download
	if !ok {
		existing = []Download{}
	} else {
		existing = *v
	}

	existing = append(existing, download)
	report.Categories[category] = &existing
	//entryCount++
	return nil
}
